package com.gaoyi.basemodule.baseUtil;

import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
import com.gaoyi.basemodule.baseCallback.Callback;
import com.gaoyi.basemodule.baseconstant.SPName;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.concurrent.TimeUnit;
import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Call;
import okhttp3.Dispatcher;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class OKHttpUtil {
    private static final String TAG = "okhttp";
    private static volatile OKHttpUtil INSTANCE;
    private static final long MAX_SIZE = 8 * 1024 * 1024;
    public static final int SEARCH_DELAY_MILLIS = 300;
//    public static final String BASE_NET_URL = "http://192.168.1.229:7099";
//    public static final String BASE_NET_URL = "http://synergosiot.ddns.net/SynPortalOW01";
//    public static final String BASE_NET_URL = "http://synergosiot.ddns.net/SynPortalOW_Deson";
//    public static final String BASE_NET_URL = "http://synergosiot.ddns.net/CRCC-PMH";
//    public static final String BASE_NET_URL = "http://synergosdemo.ddns.net/SynFourSPlatform";
//    public static final String BASE_NET_URL = "https://synergosdemo.ddns.net/SynFourSPlatform";

//    public final static String BASE_NET_URL = "http://184.168.123.134/NetGateWay";//可正常修改IP地址
    public final static String BASE_NET_URL = "http://192.168.1.229:7099";
//    public final static String BASE_NET_URL = "https://synergosdemo.ddns.net/NetGateWay";//可正常修改IP地址
    public static String NET_URL = "";
    public final static String IMG_URL = BASE_NET_URL + "/api/utils/images/";
    public final static String HELMET_IMG_URL = "/api/utils/images/helmet/";
    public final static String AI_SITE_IMG_URL = "/api/utils/images/aiSite/";
    private final OkHttpClient mClient;
    private static Handler mHandler;
    public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");

    public void post(Runnable runnable) {
        mHandler.post(runnable);
    }

    public OKHttpUtil() {
        mHandler = new Handler(Looper.getMainLooper());
        File dir = AppUtil.getContext().getFilesDir();
        Cache cache = new Cache(dir, MAX_SIZE);
        Dispatcher dispatcher = new Dispatcher();
        dispatcher.setMaxRequests(30);
        dispatcher.setMaxRequestsPerHost(10);
        mClient = new OkHttpClient.Builder()
                .dispatcher(dispatcher)
                .cache(cache)
                .connectTimeout(30, TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS)
                .callTimeout(60, TimeUnit.SECONDS)
                .addInterceptor(new CacheInterceptor())
                .addInterceptor(new TokenInterceptor())
                .addNetworkInterceptor(new HttpCacheInterceptor())
                .retryOnConnectionFailure(false)
                .build();
    }

    public static OKHttpUtil getInstance() {
        if (INSTANCE == null) {
            synchronized (OKHttpUtil.class) {
                if (INSTANCE == null) {
                    INSTANCE = new OKHttpUtil();
                }
            }
        }
        NET_URL = SPUtil.getInstance().getString(SPName.API_URL, BASE_NET_URL);
        return INSTANCE;
    }

    private void callOnFailure(Callback callback, IOException e) {
        Log.d(TAG, "result fail");
        callback.onFailed(e);
        Log.e(TAG, "callOnFailure: ", e);
    }

    public void getAsync(final String url, final Callback callback, final Type typeofT) {
        ThreadManager.getInstance().execute(() -> {
            Log.d(TAG, url);
            boolean tokenFlag = SPUtil.getInstance().getBoolean(SPName.TOKEN_FLAG, false);
            Request request = new Request.Builder()
                    .url(url)
                    .addHeader("Authorization", "Bearer " + (tokenFlag ? SPUtil.getInstance().getString(SPName.NEW_TOKEN) : SPUtil.getInstance().getString(SPName.TOKEN)))
                    .addHeader("Accept-language", LanguageUtils.getInstance().getLanguage())
                    .addHeader("projId", SPUtil.getInstance().getString(SPName.PROJ_ID))
                    .addHeader("platform", "app")
                    .get()
                    .build();
            mClient.newCall(request).enqueue(new okhttp3.Callback() {
                @Override
                public void onFailure(@NotNull Call call, @NotNull final IOException e) {
                    mHandler.post(() -> callOnFailure(callback, e));
                }

                @Override
                public void onResponse(@NotNull Call call, @NotNull Response response) {
                    try {
                        if (response.body() == null) {
                            mHandler.post(() -> callback.onFailed(new IOException()));
                            return;
                        }
                        final String result = response.body().string();
                        Log.d(TAG, result);
                        if (TextUtils.isEmpty(result)) {
                            mHandler.post(() -> callback.onFailed(new IOException()));
                        } else {
                            try {
                                Object o = GsonUtil.getInstance().fromJson(result, typeofT);
                                mHandler.post(() -> callback.onSuccess(o));
                            } catch (Exception e) {
                                mHandler.post(() -> callback.onFailed(e));
                                Log.e(TAG, "getAsync: ", e);
                            }
                        }
                    } catch (IOException e) {
                        mHandler.post(() -> callback.onFailed(e));
                    }
                }
            });
        });
    }

    public String getSync(final String url) {
        Log.d(TAG, url);
        boolean tokenFlag = SPUtil.getInstance().getBoolean(SPName.TOKEN_FLAG, false);
        Request request = new Request.Builder()
                .url(url)
                .addHeader("Authorization", "Bearer " + (tokenFlag ? SPUtil.getInstance().getString(SPName.NEW_TOKEN) : SPUtil.getInstance().getString(SPName.TOKEN)))
                .addHeader("Accept-language", LanguageUtils.getInstance().getLanguage())
                .addHeader("projId", SPUtil.getInstance().getString(SPName.PROJ_ID))
                .addHeader("platform", "app")
                .get()
                .build();
        try (Response response = mClient.newCall(request).execute()) {
            if (response.body() == null) {
                Log.d(TAG, "response.body()");
                return null;
            }
            final String result = response.body().string();
            Log.d(TAG, result);
            if (TextUtils.isEmpty(result)) {
                Log.d(TAG, "result empty");
                return null;
            } else {
                try {
                    return result;
                } catch (Exception e) {
                    e.printStackTrace();
                    return null;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            Log.d(TAG, "IOException");
            return null;
        }
    }

    public void postAsync(String url, Object json, Callback callback, Type typeofT) {
        postAsync(url, GsonUtil.getInstance().toJson(json), callback, typeofT);
    }

    public void postAsync(final String url, final String json, final Callback callback, final Type typeofT) {
        Log.e(TAG, "postAsync: " + url);
        boolean tokenFlag = SPUtil.getInstance().getBoolean(SPName.TOKEN_FLAG, false);
        ThreadManager.getInstance().execute(() -> {
            RequestBody body = RequestBody.create(json, JSON);
            Log.d(TAG, json);
            Request request = new Request.Builder()
                    .url(url)
                    .addHeader("Authorization", "Bearer " + (tokenFlag ? SPUtil.getInstance().getString(SPName.NEW_TOKEN) : SPUtil.getInstance().getString(SPName.TOKEN)))
                    .addHeader("Accept-language", LanguageUtils.getInstance().getLanguage())
                    .addHeader("projId", SPUtil.getInstance().getString(SPName.PROJ_ID))
                    .addHeader("platform", "app")
                    .post(body)
                    .build();
            mClient.newCall(request).enqueue(new okhttp3.Callback() {
                @Override
                public void onFailure(@NotNull Call call, @NotNull final IOException e) {
                    mHandler.post(() -> callOnFailure(callback, e));
                }

                @Override
                public void onResponse(@NotNull Call call, @NotNull Response response) {
                    try {
                        if (response.body() == null) {
                            mHandler.post(() -> callback.onFailed(new IOException()));
                            return;
                        }
                        final String result = response.body().string();
                        Log.d(TAG, result);
                        if (TextUtils.isEmpty(result)) {
                            Log.d(TAG, "result empty");
                            mHandler.post(() -> callback.onFailed(new IOException()));
                        } else {
                            try {
                                Object o = GsonUtil.getInstance().fromJson(result, typeofT);
                                mHandler.post(() -> callback.onSuccess(o));
                            } catch (Exception e) {
                                Log.e(TAG, "onResponse: ", e);
                                mHandler.post(() -> callback.onFailed(e));
                            }
                        }
                    } catch (IOException e) {
                        mHandler.post(() -> callback.onFailed(e));
                    }
                }
            });
        });
    }

    public void postSyncThread(String url, Object json, Callback callback, Type typeofT) {
        postSyncThread(url, GsonUtil.getInstance().toJson(json), callback, typeofT);
    }

    public void postSyncThread(final String url, final String json, final Callback callback, final Type typeofT) {
        RequestBody body = RequestBody.create(json, JSON);
        Log.d(TAG, json);
        boolean tokenFlag = SPUtil.getInstance().getBoolean(SPName.TOKEN_FLAG, false);
        Request request = new Request.Builder()
                .url(url)
                .addHeader("Authorization", "Bearer " + (tokenFlag ? SPUtil.getInstance().getString(SPName.NEW_TOKEN) : SPUtil.getInstance().getString(SPName.TOKEN)))
                .addHeader("Accept-language", LanguageUtils.getInstance().getLanguage())
                .addHeader("projId", SPUtil.getInstance().getString(SPName.PROJ_ID))
                .addHeader("platform", "app")
                .post(body)
                .build();
        mClient.newCall(request).enqueue(new okhttp3.Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull final IOException e) {
                callOnFailure(callback, e);
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) {
                try {
                    if (response.body() == null) {
                        mHandler.post(() -> callback.onFailed(new IOException()));
                        return;
                    }
                    final String result = response.body().string();
                    Log.d(TAG, "result:" + result);
                    if (TextUtils.isEmpty(result)) {
                        Log.d(TAG, "result empty");
                        callback.onFailed(new IOException());
                    } else {
                        try {
                            Object o = GsonUtil.getInstance().fromJson(result, typeofT);
                            callback.onSuccess(o);
                        } catch (Exception e) {
                            Log.e(TAG, "postSyncThread: ", e);
                            callback.onFailed(e);
                        }
                    }
                } catch (IOException e) {
                    Log.e(TAG, "postSyncThread: ", e);
                    callback.onFailed(e);
                }
            }
        });
    }
}

class CacheInterceptor implements Interceptor {

    @NotNull
    @Override
    public Response intercept(@NotNull Chain chain) throws IOException {
        Request request = chain.request();
        if (NetworkUtil.isConnected()) {
            request = request.newBuilder()
                    .cacheControl(CacheControl.FORCE_NETWORK)
                    .build();
        } else { // 如果没有网络，则返回缓存未过期一个月的数据
            request = request.newBuilder()
                    .cacheControl(CacheControl.FORCE_CACHE)
                    .build();
        }
        return chain.proceed(request);
    }
}

class HttpCacheInterceptor implements Interceptor {

    @NotNull
    @Override
    public Response intercept(@NotNull Chain chain) throws IOException {
        Response response = chain.proceed(chain.request());
        return response.newBuilder()
                .removeHeader("Pragma")
                .removeHeader("Cache-Control")
                .header("Cache-Control", "public, max-age=" + 24 * 30 * 6000)
                .build();
    }
}
